/*
 * \brief  Core-internal dataspace representation
 * \author Norman Feske
 * \author Christian Helmuth
 * \date   2006-07-20
 */

/*
 * Copyright (C) 2006-2009 Norman Feske
 * Genode Labs, Feske & Helmuth Systementwicklung GbR
 *
 * This file is part of the Genode OS framework, which is distributed
 * under the terms of the GNU General Public License version 2.
 */

#ifndef _CORE__INCLUDE__DATASPACE_COMPONENT_H_
#define _CORE__INCLUDE__DATASPACE_COMPONENT_H_

/* Genode */
#include <base/printf.h>
#include <base/lock_guard.h>
#include <util/list.h>
#include <dataspace/server.h>

/* Core */
#include <util.h>

namespace Genode {

	class Rm_region;
	class Rm_session_component;

	class Dataspace_component : public Dataspace_server
	{
		private:

			addr_t _phys_addr;        /* address of dataspace in physical memory */
			addr_t _core_local_addr;  /* address of core-local mapping           */
			size_t _size;             /* size of dataspace in bytes              */

			List<Rm_region> _regions;  /* regions this is attached to */
			Lock            _lock;

			/*
			 * Prevent copy-construction of objects with virtual functions.
			 */
			Dataspace_component(const Dataspace_component&);

		public:

			/**
			 * Default constructor returning an invalid dataspace
			 */
			Dataspace_component() : _phys_addr(0), _core_local_addr(0), _size(0) { }

			/**
			 * Constructor for dataspaces having the core-local address as the physical address
			 *
			 * This constructor is used by RAM and ROM dataspaces.
			 */
			Dataspace_component(size_t size, addr_t core_local_addr)
			: _phys_addr(core_local_addr), _core_local_addr(core_local_addr), _size(size) { }

			/**
			 * Constructor for dataspaces with different core-local and physical addresses
			 *
			 * This constructor is used by IO_MEM. Because I/O-memory areas may be located
			 * at addresses that are populated by data or text in Core's virtual address
			 * space, we need to map these areas to another core-local address. The local
			 * mapping in core's address space is needed to send a mapping to another
			 * address space.
			 */
			Dataspace_component(size_t size, addr_t core_local_addr, addr_t phys_addr)
			: _phys_addr(phys_addr), _core_local_addr(core_local_addr), _size(size) 
			{ }

			/**
			 * Destructor
			 */
			~Dataspace_component();

			/**
			 * Return region-manager session corresponding to nested dataspace
			 *
			 * \retval  0  dataspace is not a nested dataspace
			 */
			virtual Rm_session_component *sub_rm_session() { return 0; }


			/*****************************
			 ** Dataspace RPC interface **
			 *****************************/

			size_t size()            { return _size; }
			addr_t phys_addr()       { return _phys_addr; }
			addr_t core_local_addr() { return _core_local_addr; }


			/*************************************
			 ** L4-specific dataspace interface **
			 *************************************/

			virtual void map_page(off_t offset, bool write);
			void unmap();

			void attached_to(Rm_region *region);
			void detached_from(Rm_region *region);
	};
}

#endif /* _CORE__INCLUDE__DATASPACE_COMPONENT_H_ */
